import sys
import ply.yacc as yacc
import ply.lex as lex
sys.path.insert(0,"../..")

names = { }
result = None
error = False

tokens = (
    'NAME','BOOLEAN'
    )

literals = ['&','|','=','!','(',')']

# Tokens
t_NAME    = r'[ug]\d+'
t_BOOLEAN = r'[01]'
t_ignore = " \t"

def t_newline(t):
    r'\n+'
    t.lexer.lineno += t.value.count("\n")
    
def t_error(t):
    global error
    error = True
    t.lexer.skip(1)

# Parsing rules
precedence = (
    ('left','&','|'),
    ('right','NEGATION'),
    )

def p_statement_assign(p):
    "statement : NAME '=' BOOLEAN"
    if p[3] == '1':
        names[p[1]] = True
    else:
        names[p[1]] = False

# Parse CNF
def p_statement_expr(p):
    '''statement : orexpression 
                 | andexpression '''
    global result
    result = p[1]

def p_expression_orop(p):
    '''orexpression : orexpression '|' orbexpression
                    | orbexpression'''
    if len(p) > 2:
        p[0] = p[1] or p[3]
    else:
        p[0] = p[1]

def p_expression_andp(p):
    '''orbexpression : '(' andexpression ')' 
                     | atomic'''
    if len(p) > 2:
        p[0] = p[2]
    else:
        p[0] = p[1]

def p_expression_andop(p):
    '''andexpression : andexpression '&' atomic
                     | atomic'''
    if len(p) > 2: 
        p[0] = p[1] and p[3]
    else:
        p[0] = p[1]

def p_expression_atomic(p):
    '''atomic : '!' NAME %prec NEGATION
              | NAME'''
    if len(p) > 2: 
        p[0] = not p[2]
    else:
        try:
            p[0] = names[p[1]]
        except LookupError:
            p[0] = False

def p_error(p):
    global error
    error = True

def check_permission(uid, gids, formula):
    global names
    global result
    global error
    error = False
    names = { }
    result = None
    lex.lex()
    yacc.yacc()
    if not uid == None:
        yacc.parse('u' + str(uid) + '=1')
    if not gids == None:
        for gid in gids:
            yacc.parse('g' + str(gid) + '=1')
    yacc.parse(str(formula))
    return not error and result

def validate(formula):
    global error
    error = False
    lex.lex()
    yacc.yacc()
    yacc.parse(str(formula))
    return not error
